﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SimpleEncryption.CryptoSteps;
using SimpleEncryption.DecriptionSteps;

namespace SimpleEncryption
{
    public static class CryptoStepGenerator 
    {
        public static Random random = new Random();

        /// <summary>
        /// Generates a number of scrambled position crypto steps
        /// </summary>
        /// <param name="numberOfSteps">The number of steps to generate with randomised ScrambledRelations</param>
        /// <param name="numberOfstringToMove">The number ofstring to move.</param>
        /// <returns></returns>
        public static IEnumerable<ScramblePositions> GenerateScrambledPositionSteps(int numberOfSteps, int numberOfstringToMove)
        {
            List<ScramblePositions> scramblePositions = new List<ScramblePositions>();
            for (int currentStep = 0; currentStep < numberOfSteps; currentStep++)
            {
               
                var scramblePosition = new ScramblePositions();
                scramblePositions.Add(scramblePosition);
                for (int i = 0; i < numberOfstringToMove; i++)
                {
                    var startPosition = random.Next();
                    var numberOfMoves = random.Next();
                    if (scramblePosition.ScrambledRelations.Any(x => x.Key == startPosition))
                    {
                        continue;
                    }
                    scramblePosition.ScrambledRelations.Add(startPosition, numberOfMoves);
                }
            }
            return scramblePositions;
        }
        private static List<char> allChars = Enumerable.Range(0, char.MaxValue + 1)
          .Select(i => (char)i)
          .Where(c => !char.IsControl(c))
          .ToList();
        /// <summary>
        /// Generates the scrambled position steps.
        /// </summary>
        /// <param name="numberOfSteps">The number of steps.</param>
        /// <returns></returns>
        public static IEnumerable<ScramblePositions> GenerateScrambledPositionSteps(int numberOfSteps)
        {
           return GenerateScrambledPositionSteps(numberOfSteps, random.Next(1, 100));
        }
        private static object lockObject = new object();
        public static IEnumerable<LetterReplacement> GenerateLetterReplacement(int numberOfSteps)
        {

            List<LetterReplacement> letterReplacements = new List<LetterReplacement>();
            Parallel.For(0, numberOfSteps, (step, state) =>
            {
                    random = new Random();
                    LetterReplacement letterReplacement = new LetterReplacement();
                    lock (lockObject)
                    {
                        letterReplacements.Add(letterReplacement);
                    }
                    var allCharsCopy = allChars.ToList();
                    var allCharsCopyTarget = allChars.ToList();
                    while (allCharsCopy.Count > 1)
                    {
                        var charKey = allCharsCopy.GetRandom();
                        allCharsCopy.Remove(charKey);
                        var charValue = allCharsCopyTarget.GetRandom();
                        allCharsCopyTarget.Remove(charValue);
                        letterReplacement.LetterReleations.Add(charKey, charValue);

                    }
                });
         
            return letterReplacements;
        } 

        public static T GetRandom<T>(this IList<T> list)
        {
            if (!list.Any())
            {
                return default(T);
            }
            return list[random.Next(0, list.Count())];
        }
        public static T GetRandom<T>(this IEnumerable<T> collection)
        {
            return GetRandom(collection.ToList());
        }
    }
}
